#include "clib_container_stack.h"
#include "../vector/clib_container_vector.h"

struct clib_container_stack {
    struct clib_container_vector *vector;

    void *(*mem_malloc_func)(size_t size);

    void (*mem_free_func)(void *block);

    void *(*mem_copy_func)(void *target,const void *src, size_t size);
};


int clib_container_stack_create_with_conf(struct clib_container_stack_conf *conf,
                                          struct clib_container_stack **out) {
    clib_check_if_true_return_value(conf == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_copy_func == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_malloc_func == NULL, CLIB_RES_PARAM_ERROR);
    clib_check_if_true_return_value(conf->mem_free_func == NULL, CLIB_RES_PARAM_ERROR);
    struct clib_container_stack *stack = conf->mem_malloc_func(sizeof(struct clib_container_stack));
    if (!stack) {
        return CLIB_RES_MEMORY_ERROR;
    }
    stack->mem_malloc_func = conf->mem_malloc_func;
    stack->mem_free_func = conf->mem_free_func;
    stack->mem_copy_func = conf->mem_copy_func;

    struct clib_container_vector_conf vector_conf;

    vector_conf.mem_free_func = conf->mem_free_func;
    vector_conf.mem_copy_func = conf->mem_copy_func;
    vector_conf.mem_malloc_func = conf->mem_malloc_func;
    vector_conf.capacity = 8;

    struct clib_container_vector *array;
    if (clib_container_vector_create_with_conf(&vector_conf, &array) == CLIB_RES_OK) {
        stack->vector = array;
    } else {
        conf->mem_free_func(stack);
        return CLIB_RES_MEMORY_ERROR;
    }
    *out = stack;
    return CLIB_RES_OK;
}


void clib_container_stack_destroy(struct clib_container_stack *stack) {
    clib_container_vector_destroy(stack->vector);
    stack->mem_free_func(stack);
}

int clib_container_stack_push(struct clib_container_stack *stack, void *element) {
    return clib_container_vector_add(stack->vector, element);
}

int clib_container_stack_peek(struct clib_container_stack *stack, void **out) {
    return clib_container_vector_get_last(stack->vector, out);
}

int clib_container_stack_pop(struct clib_container_stack *stack, void **out) {
    return clib_container_vector_remove_last(stack->vector, out);
}

size_t clib_container_stack_get_current_size(struct clib_container_stack *stack) {
    return clib_container_vector_get_current_size(stack->vector);
}